#ifndef X86_H
#define X86_H

#include "crossbit/common.h"
#include <cassert>
#include <iostream>
#include <string>

namespace crossbit {

		class X86 {
				public:

						/* Encoding of Conditional Test (tttn) Field */
						static const XTUint8 EQ = 0x4;	    /* 0100 */
						static const XTUint8 NE = 0x5;	    /* 0101 */
						static const XTUint8 NA = 0x6;	    /* 0110 */
						static const XTUint8 GT = 0xf;	    /* 1111 */
						static const XTUint8 GE = 0xd;	    /* 1101 */
						static const XTUint8 LT = 0xc;	    /* 1100 */ 
						static const XTUint8 LE = 0xe;	    /* 1110 */
						static const XTUint8 AB = 0x7;	    /* 0111 */
						static const XTUint8 BE = 0x2;	    /* 0010 */

						static const XTUint8 CCENCODINGS[9];
						static const XTUint8 ANTICCENCODINGS[8];

						/* Encoding of General-purpose register field */
						static const XTRegNum EAX = 0;
						static const XTRegNum ECX = 1;
						static const XTRegNum EDX = 2;
						static const XTRegNum EBX = 3;
						static const XTRegNum ESP = 4;
						static const XTRegNum EBP = 5;
						static const XTRegNum ESI = 6;
						static const XTRegNum EDI = 7;

						// mapping regnum to the name
						static const std::string REG2STR[8];

						static inline void setP(XTMemAddr p)
						{
								cur_p = p;
						}

						static inline XTMemAddr getP()
						{
								return cur_p;
						}

						static void putWord(XTInt32 word)
						{
								*((XTInt32 *)cur_p) = word;
								cur_p += 4;
						}

						//added by zhengjuyu
						static inline void nop()
						{
								*((XTUint8*)cur_p++) = 0x90;
						}

	    static inline void inc(RegNum reg)
	    {
		      *((XTUint8*)cur_p++) = 0x40 | reg;
	    }

	    static inline void dec(RegNum reg)
	    {
		      *((XTUint8*)cur_p++) = 0x48 | reg;
	    }

						// 01 /r	ADD r/m32, r32	    Add r32 to r/m32
						/* 0000 000w : 11 reg1 reg2 */
						static inline void addRegToReg(XTRegNum reg1, XTRegNum reg2)
						{   
								*((XTUint8*)cur_p++) = 0x01;
								*((XTUint8*)cur_p++) = 0xc0 | (reg1 << 3) | reg2;
						}
						/* inc reg*/
						static inline void inc( XTRegNum reg ){
								*((XTUint8*)cur_p++) = 0x40 | reg ;
						}

						/* 0000 000w : mod reg r/m : disp32*/
						static inline void addRegToMem(XTRegNum reg, XTMemAddr mem)
						{
								*((XTUint8*)cur_p++) = 0x01;
								*((XTUint8*)cur_p++) = (reg << 3) | 0x05; /* mod:00 reg r/m:101 */
								putWord(mem);
						}

						/* 1000 00sw : 11 000 reg : immediate data  */
						static inline void addImmToReg(XTInt32 imm, XTRegNum reg)
						{
								*((XTUint8*)cur_p++) = 0x81;
								*((XTUint8*)cur_p++) = 0xc0 | reg;
								putWord(imm);
						}

	    static inline void addImm8ToReg(Byte imm, RegNum reg)
	    {
										*((XTUint8*)cur_p++) = 0x83;
										*((XTUint8*)cur_p++) = 0xc0 | reg;
										*((XTUint8*)cur_p++) = imm;
	    }


						/* 0010 000w : 11 reg1 reg2 */
						static inline void andRegToReg(XTRegNum reg1, XTRegNum reg2)
						{
								*((XTUint8*)cur_p++) = 0x21;
								*((XTUint8*)cur_p++) = 0xc0 | (reg1 << 3) | reg2;
						}

						/* 1000 00sw : 11 100 reg : immediate data */
						static inline void andImmToReg(XTInt32 imm, XTRegNum reg)
						{
								*((XTUint8*)cur_p++) = 0x81;
								*((XTUint8*)cur_p++) = 0xe0 | reg;
								putWord(imm);
						}

						/* 0011 000w : 11 reg1 reg2 */
						static inline void xorRegToReg(XTRegNum reg1, XTRegNum reg2)
						{
								*((XTUint8*)cur_p++) = 0x31;
								*((XTUint8*)cur_p++) = 0xc0 | (reg1 << 3) | reg2;
						}

						/* 1000 00sw : 11 110 reg : immediate data */
						static inline void xorImmToReg(XTInt32 imm, XTRegNum reg)
						{
								*((XTUint8*)cur_p++) = 0x81;
								*((XTUint8*)cur_p++) = 0xf0 | reg;
								putWord(imm);
						}

						/* 0000 100w : 11 reg1 reg2 */
						static inline void orRegToReg(XTRegNum reg1, XTRegNum reg2)
						{
								*((XTUint8*)cur_p++) = 0x09;
								*((XTUint8*)cur_p++) = 0xc0 | (reg1 << 3) | reg2;
						}

						/* 1000 00sw : 11 001 reg : immediate data */
						static inline void orImmToReg(XTInt32 imm, XTRegNum reg)
						{
								*((XTUint8*)cur_p++) = 0x81;
								*((XTUint8*)cur_p++) = 0xc8 | reg;
								putWord(imm);
						}

						/* 0010 100w : 11 reg1 reg2 */
						static inline void subRegFromReg(XTRegNum reg1, XTRegNum reg2)
						{
								*((XTUint8*)cur_p++) = 0x29;
								*((XTUint8*)cur_p++) = 0xc0 | (reg1 << 3) | reg2;
						}

						/* 1000 000w : 11 101 reg : immediate data */
						static inline void subImmFromReg(XTInt32 imm, XTRegNum reg)
						{
								*((XTUint8*)cur_p++) = 0x81;
								*((XTUint8*)cur_p++) = 0xe8 | reg;
								putWord(imm);
						}

						/* 1000 000w : 11 101 reg : immediate data  */
						static inline void subImm8FromReg(XTUint8 imm, XTRegNum reg)
						{
								*((XTUint8*)cur_p++) = 0x80;
								*((XTUint8*)cur_p++) = 0xe8 | reg;
								*((XTUint8*)cur_p++) = imm;
						}

						/* 1111 011w : 11 010 reg */
						static inline void notReg(XTRegNum reg)
						{
								*((XTUint8*)cur_p++) = 0xf7;
								*((XTUint8*)cur_p++) = 0xd0 | reg;
						}

						/* 1111 011w : 11 011 reg */
						static inline void negReg(XTRegNum reg)
						{
								*((XTUint8*)cur_p++) = 0xf7;
								*((XTUint8*)cur_p++) = 0xd8 | reg;
						}

						/* 1100 000w : 11 100 reg : imm8 data */
						static inline void shlRegByImm(XTRegNum reg, XTUint8 imm)
						{
								*((XTUint8*)cur_p++) = 0xc1;
								*((XTUint8*)cur_p++) = 0xe0 | reg;
								*(( XTPStr )cur_p++) = imm;
						}

						/* 1101 001w : 11 100 reg */
						static inline void shlRegByCl(XTRegNum reg)
						{
								*((XTUint8*)cur_p++) = 0xd3;
								*((XTUint8*)cur_p++) = 0xe0 | reg;
						}

						/* 1100 000w : 11 111 reg : imm8 data */
						static inline void sarRegByImm(XTRegNum reg, XTUint8 imm)
						{
								*((XTUint8*)cur_p++) = 0xc1;
								*((XTUint8*)cur_p++) = 0xf8 | reg;
								*(( XTPStr )cur_p++) = imm;
						}

						/* 1101 001w : 11 111 reg */
						static inline void sarRegByCl(XTRegNum reg)
						{
								*((XTUint8*)cur_p++) = 0xd3;
								*((XTUint8*)cur_p++) = 0xf8 | reg;
						}

						/* 1100 000w : 11 101 reg : imm8 data */
						static inline void shrRegByImm(XTRegNum reg, XTUint8 imm)
						{
								*((XTUint8*)cur_p++) = 0xc1;
								*((XTUint8*)cur_p++) = 0xe8 | reg;
								*(( XTPStr )cur_p++) = imm;
						}

						/* 1101 001w : 11 101 reg */
						static inline void shrRegByCl(XTRegNum reg)
						{
								*((XTUint8*)cur_p++) = 0xd3;
								*((XTUint8*)cur_p++) = 0xe8 | reg;
						}

						/* 1111 011w : 11 101 reg */
						static inline void imulEaxToReg(XTRegNum reg)
						{
								*((XTUint8*)cur_p++) = 0xf7;
								*((XTUint8*)cur_p++) = 0xe8 | reg;
						}

						/* 1111 011w : 11 100 reg */
						static inline void mulEaxToReg(XTRegNum reg)
						{
								*((XTUint8*)cur_p++) = 0xf7;
								*((XTUint8*)cur_p++) = 0xe0 | reg;
						}

						/* 1111 011w : 11 111 reg */
						static inline void idivEdxEaxByReg(XTRegNum reg)
						{
								*((XTUint8*)cur_p++) = 0xf7;
								*((XTUint8*)cur_p++) = 0xf8 | reg;
						}

						/* 111 011w : 11 110 reg */
						static inline void divEdxEaxByReg(XTRegNum reg)
						{
								*((XTUint8*)cur_p++) = 0xf7;
								*((XTUint8*)cur_p++) = 0xf0 | reg;
						}

						/* 1100 011w : 11 000 reg : immediate data */
						static inline void movwImmToReg(XTInt32 imm, XTRegNum reg)
						{
								*((XTUint8*)cur_p++) = 0xc7; /* 1100 011w, w = 1 */
								*((XTUint8*)cur_p++) = 0xc0 | reg;
								putWord(imm);
						}


						static inline void movImmToMem(XTInt32 imm, XTMemAddr mem, BlockSize size)
						{
								switch(size)
								{
										case BYTE: movbImmToMem(imm, mem); break;
										case HALFWORD: movhImmToMem(imm, mem); break;
										case WORD: movwImmToMem(imm, mem); break;
								}

						}

						static inline void movbImmToMem(XTInt32 imm, XTMemAddr mem)
						{
								*((XTUint8*)cur_p++) = 0xc6;
								*((XTUint8*)cur_p++) = 0x5;
								putWord(mem);
								*((XTUint8*)cur_p++) = (XTInt8)imm;
						}

						static inline void movhImmToMem(XTInt32 imm, XTMemAddr mem)
						{
								*((XTUint8*)cur_p++) = 0x66;
								*((XTUint8*)cur_p++) = 0xc7;
								*((XTUint8*)cur_p++) = 0x5;
								putWord(mem);
								*((XTUint16*)(cur_p)) = (XTUint16)imm;
								cur_p += 2;
						}

						/* 1100 011w : mod 000 r/m : immediate data*/
						static inline void movwImmToMem(XTInt32 imm, XTMemAddr mem)
						{
								*((XTUint8*)cur_p++) = 0xc7;
								*((XTUint8*)cur_p++) = 0x5; /* mod:00 000 r/m:101 */
								putWord(mem);
								putWord(imm);
						}

						static inline void movImmToMem(XTInt32 imm, XTRegNum reg, XTInt32 disp, BlockSize size)
						{
								switch(size)
								{
										case WORD: movwImmToMem(imm, reg, disp);break;
										case HALFWORD: movhImmToMem(imm, reg, disp);break;
										case BYTE: movbImmToMem(imm, reg, disp);break;
								}
						}

						static inline void movbImmToMem(XTInt32 imm, XTRegNum reg, XTInt32 disp)
						{
								*((XTUint8*)cur_p++) = 0xc6;
								*((XTUint8*)cur_p++) = 0x80 | reg;
								putWord(disp);
								*((XTUint8*)cur_p++) = (XTInt8)imm;
						}

						static inline void movhImmToMem(XTInt32 imm, XTRegNum reg, XTInt32 disp)
						{
								*((XTUint8*)cur_p++) = 0x66;
								*((XTUint8*)cur_p++) = 0xc7;
								*((XTUint8*)cur_p++) = 0x80 | reg;
								putWord(disp);
								*((XTUint16*)(cur_p)) = (XTUint16)imm;
								cur_p += 2;
						}

						/* 1100 011w : mod 000 r/m : immediate data*/
						static inline void movwImmToMem(XTInt32 imm, XTRegNum reg, XTInt32 disp)
						{
								*((XTUint8*)cur_p++) = 0xc7;
								*((XTUint8*)cur_p++) = 0x80 | reg; /* mod:10 000 r/m:reg */
								putWord(disp);
								putWord(imm);
						}

						static inline void movMemToReg(XTMemAddr mem, BlockSize size, XTRegNum dst)
						{
								switch (size) {
										case WORD:	    movwMemToReg(mem, dst); break;
										case HALFWORD:  movhMemToReg(mem, dst); break;
										case BYTE:	    movbMemToReg(mem, dst); break;
								}
						}

						/* 1000 1011 : mod reg r/m  */
						static inline void movwMemToReg(XTMemAddr mem, XTRegNum dst)
						{
								*((XTUint8*)cur_p++) = 0x8b;    /* 1000 1011 */
								*((XTUint8*)cur_p++) = dst << 3 | 0x5;  /* mod:00, reg, r/m:101 */
								putWord(mem);
						}

						/* 1000 1010 : mod reg r/m  */
						static inline void movbMemToReg(XTMemAddr mem, XTRegNum dst)
						{
								*((XTUint8*)cur_p++) = 0x8a;    /* 1000 1011 */
								*((XTUint8*)cur_p++) = dst << 3 | 0x5;  /* mod:00, reg, r/m:101 */
								*((XTUint32*)cur_p) = (XTUint32)mem;	/* discur_p32 */
								cur_p += 4;
						}

						/* prefix:0x66 1000 1011 : mod reg r/m  */
						static inline void movhMemToReg(XTMemAddr mem, XTRegNum dst)
						{
								*((XTUint8*)cur_p++) = 0x66;
								*((XTUint8*)cur_p++) = 0x8b;    /* 1000 1011 */
								*((XTUint8*)cur_p++) = dst << 3 | 0x5;  /* mod:00, reg, r/m:101 */
								*((XTUint32*)cur_p) = (XTUint32)mem;	/* discur_p32 */
								cur_p += 4;
						}

						static inline void movMemToReg(XTRegNum reg, XTInt32 disp, BlockSize size, XTRegNum dst)
						{
								switch (size) {
										case WORD:		movwMemToReg(reg, disp, dst); break;
										case HALFWORD:	movhMemToReg(reg, disp, dst); break;
										case BYTE:		movbMemToReg(reg, disp, dst); break;
								}
						}

						/* 1000 1011 : mod reg r/m  */
						static inline void movwMemToReg(XTRegNum reg, XTInt32 disp, XTRegNum dst)
						{
								assert(reg != ESP);
								*((XTUint8*)cur_p++) = 0x8b;
								*((XTUint8*)cur_p++) = 0x80 | (dst << 3) | reg;    /* mod:10, dst, r/m:reg */
								*((XTInt32 *)cur_p) =  disp;
								cur_p += 4;
						}

						/* 1000 1010 : mod reg r/m  */
						static inline void movbMemToReg(XTRegNum reg, XTInt32 disp, XTRegNum dst)
						{
								assert(reg != ESP);
								*((XTUint8*)cur_p++) = 0x8a;
								*((XTUint8*)cur_p++) = 0x80 | (dst << 3) | reg;    /* mod:10, dst, r/m:reg */
								*((XTInt32 *)cur_p) =  disp;
								cur_p += 4;
						}

						/* prefix:0x66 1000 1011 : mod reg r/m  */
						static inline void movhMemToReg(XTRegNum reg, XTInt32 disp, XTRegNum dst)
						{
								assert(reg != ESP);
								*((XTUint8*)cur_p++) = 0x66;
								*((XTUint8*)cur_p++) = 0x8b;
								*((XTUint8*)cur_p++) = 0x80 | (dst << 3) | reg;    /* mod:10, dst, r/m:reg */
								*((XTInt32 *)cur_p) =  disp;
								cur_p += 4;
						}


						static inline void movMemToReg(XTRegNum src, BlockSize size, XTRegNum dst)
						{
								switch (size) {
										case WORD:		movwMemToReg(src, dst); break;
										case HALFWORD:	movhMemToReg(src, dst); break;
										case BYTE:		movbMemToReg(src, dst); break;
								}
						}

						/* 1000 1011 : mod dst r/m */
						static inline void movwMemToReg(XTRegNum src, XTRegNum dst)
						{
								assert(src != ESP && src != EBP);
								*((XTUint8*)cur_p++) = 0x8b;
								*((XTUint8*)cur_p++) = (dst << 3) | src; /* mod:00 dst r/m:src */
						}

						/* 1000 1010 : mod dst r/m */
						static inline void movbMemToReg(XTRegNum src, XTRegNum dst)
						{
								assert(src != ESP && src != EBP);
								*((XTUint8*)cur_p++) = 0x8a;
								*((XTUint8*)cur_p++) = (dst << 3) | src; /* mod:00 dst r/m:src */
						}

						/* prefix:0x66 1000 1011 : mod dst r/m */
						static inline void movhMemToReg(XTRegNum src, XTRegNum dst)
						{
								assert(src != ESP && src != EBP);
								*((XTUint8*)cur_p++) = 0x66;
								*((XTUint8*)cur_p++) = 0x8b;
								*((XTUint8*)cur_p++) = (dst << 3) | src; /* mod:00 dst r/m:src */
						}

						static inline void movRegToMem(XTRegNum reg, BlockSize size, XTMemAddr addr)
						{
								switch (size) {
										case WORD:		movwRegToMem(reg, addr); break;
										case HALFWORD:	movhRegToMem(reg, addr); break;
										case BYTE:		movbRegToMem(reg, addr); break;
								}
						}

						/* 1000 1001 : mod reg r/m */
						static inline void movwRegToMem(XTRegNum reg, XTMemAddr addr)
						{
								*((XTUint8*)cur_p++) = 0x89;    /* 1000 1001 */
								*((XTUint8*)cur_p++) = reg << 3 | 0x5;  /* mod:00, reg, r/m:101 */
								*((XTUint32*)cur_p) = (XTUint32)addr;	/* discur_p32 */
								cur_p += 4;
						}

						/* 1000 1000 : mod reg r/m */
						static inline void movbRegToMem(XTRegNum reg, XTMemAddr addr)
						{
								*((XTUint8*)cur_p++) = 0x88;    /* 1000 1001 */
								*((XTUint8*)cur_p++) = reg << 3 | 0x5;  /* mod:00, reg, r/m:101 */
								*((XTUint32*)cur_p) = (XTUint32)addr;	/* discur_p32 */
								cur_p += 4;
						}

						/* prefix:0x66 1000 1001 : mod reg r/m */
						static inline void movhRegToMem(XTRegNum reg, XTMemAddr addr)
						{
								*((XTUint8*)cur_p++) = 0x66;
								*((XTUint8*)cur_p++) = 0x89;    /* 1000 1001 */
								*((XTUint8*)cur_p++) = reg << 3 | 0x5;  /* mod:00, reg, r/m:101 */
								*((XTUint32*)cur_p) = (XTUint32)addr;	/* discur_p32 */
								cur_p += 4;
						}


						static inline void movRegToMem(XTRegNum src, BlockSize size, XTRegNum reg, XTInt32 disp)
						{
								switch (size) {
										case WORD:		movwRegToMem(src, reg, disp); break;
										case HALFWORD:	movhRegToMem(src, reg, disp); break;
										case BYTE:		movbRegToMem(src, reg, disp); break;
								}
						}

						/* 1000 1001 : mod reg r/m */
						static inline void movwRegToMem(XTRegNum src, XTRegNum reg, XTInt32 disp)
						{
								assert(reg != ESP);
								*((XTUint8*)cur_p++) = 0x89;
								*((XTUint8*)cur_p++) = 0x80 | (src << 3) | reg;
								*((XTInt32 *)cur_p) = disp;
								cur_p += 4;
						}

						/* 1000 1000 : mod reg r/m */
						static inline void movbRegToMem(XTRegNum src, XTRegNum reg, XTInt32 disp)
						{
								assert(reg != ESP);
								*((XTUint8*)cur_p++) = 0x88;
								*((XTUint8*)cur_p++) = 0x80 | (src << 3) | reg;
								*((XTInt32 *)cur_p) = disp;
								cur_p += 4;
						}

						/* 1000 1001 : mod reg r/m */
						static inline void movhRegToMem(XTRegNum src, XTRegNum reg, XTInt32 disp)
						{
								assert(reg != ESP);
								*((XTUint8*)cur_p++) = 0x66;
								*((XTUint8*)cur_p++) = 0x89;
								*((XTUint8*)cur_p++) = 0x80 | (src << 3) | reg;
								*((XTInt32 *)cur_p) = disp;
								cur_p += 4;
						}



						static inline void movRegToMem(XTRegNum src, BlockSize size, XTRegNum dst)
						{
								switch (size) {
										case WORD:		movwRegToMem(src, dst); break;
										case HALFWORD:	movhRegToMem(src, dst); break;
										case BYTE:		movbRegToMem(src, dst); break;
								}
						}

						/* 1000 1001 : mod src r/m */
						static inline void movwRegToMem(XTRegNum src, XTRegNum dst)
						{
								assert(dst != ESP && dst != EBP);
								*((XTUint8*)cur_p++) = 0x89;
								*((XTUint8*)cur_p++) = (src << 3) | dst;
						}

						/* 1000 1000 : mod src r/m */
						static inline void movbRegToMem(XTRegNum src, XTRegNum dst)
						{
								assert(dst != ESP && dst != EBP);
								*((XTUint8*)cur_p++) = 0x88;
								*((XTUint8*)cur_p++) = (src << 3) | dst;
						}

						/* prefix:0x66 1000 1001 : mod src r/m */
						static inline void movhRegToMem(XTRegNum src, XTRegNum dst)
						{
								assert(dst != ESP && dst != EBP);
								*((XTUint8*)cur_p++) = 0x66;
								*((XTUint8*)cur_p++) = 0x89;
								*((XTUint8*)cur_p++) = (src << 3) | dst;
						}

						/* 1000 101w : 11 dst src */
						static inline void movwRegToReg(XTRegNum reg1, XTRegNum reg2)
						{
								*((XTUint8*)cur_p++) = 0x8b;   /* 1000 1011 */ 
								*((XTUint8*)cur_p++) = 0xc0 | (reg2 << 3) | reg1;	/* 11 reg1 reg2 */
						}

						static inline void movbRegToReg(XTRegNum reg1, XTRegNum reg2)
						{
								*((XTUint8*)cur_p++) = 0x8a;
								*((XTUint8*)cur_p++) = 0xc0 | ( reg2 << 3) | reg1;
						}

						/* 0000 1111 : 1011 1110 : 11 dst src */
						static inline void movsblRegToReg(XTRegNum src, XTRegNum dst)
						{
								*((XTUint8*)cur_p++) = 0x0f;
								*((XTUint8*)cur_p++) = 0xbe;
								*((XTUint8*)cur_p++) = 0xc0 | (dst << 3) | src;
						}

						/* 0000 1111 : 1011 1111 : 11 dst src */
						static inline void movswlRegToReg(XTRegNum src, XTRegNum dst)
						{
								*((XTUint8*)cur_p++) = 0x0f;
								*((XTUint8*)cur_p++) = 0xbf;
								*((XTUint8*)cur_p++) = 0xc0 | (dst << 3) | src;
						}

						/* 0000 1111 : 1011 0110 : 11 dst src */
						static inline void movzblRegToReg(XTRegNum src, XTRegNum dst)
						{
								*((XTUint8*)cur_p++) = 0x0f;
								*((XTUint8*)cur_p++) = 0xb6;
								*((XTUint8*)cur_p++) = 0xc0 | (dst << 3) | src;
						}

						/* 0000 1111 : 1011 0111 : 11 dst src */
						static inline void movzwlRegToReg(XTRegNum src, XTRegNum dst)
						{
								*((XTUint8*)cur_p++) = 0x0f;
								*((XTUint8*)cur_p++) = 0xb7;
								*((XTUint8*)cur_p++) = 0xc0 | (dst << 3) | src;
						}

						/* 1100 0011 */
						static inline void ret()
						{
								*((XTUint8*)cur_p++) = 0xc3;
						}

						/* 0011 100w : 11 reg2 reg1 */
						static inline void cmpRegWithReg(XTRegNum reg1, XTRegNum reg2)
						{
								*((XTUint8*)cur_p++) = 0x39;
								*((XTUint8*)cur_p++) = 0xc0 | (reg2 << 3) | reg1;
						}


						/* 1000 0001 : 11 111 reg : immediate data */
						static inline void cmpImmWithReg(XTInt32 imm, XTRegNum reg)
						{
								*((XTUint8*)cur_p++) = 0x81;
								*((XTUint8*)cur_p++) = 0xf8 | reg;
								putWord(imm);
						}

						static inline void fcmpFpregWithFpregPop()
						{
								*((XTUint8*)cur_p++) = 0xdf;
								*((XTUint8*)cur_p++) = 0xf1;
						}

						/* 1000 0101 : 11 reg1 reg2 */
						static inline void testRegWithReg(XTRegNum reg1, XTRegNum reg2)
						{
								*((XTUint8*)cur_p++) = 0x85;
								*((XTUint8*)cur_p++) = 0xc0 | (reg1 << 3) | reg2;
						}

						/* 0000 1111 : 1001 tttn : 11 000 reg */
						static inline void setcc(XTRegNum reg, XTUint8 tttn)
						{
								*((XTUint8*)cur_p++) = 0x0f;
								*((XTUint8*)cur_p++) = 0x90 | tttn;
								*((XTUint8*)cur_p++) = 0xc0 | reg;
						}

	    static inline void jecxz(Byte disp)
	    {
		*((XTUint8*)cur_p++) = 0xe3;
		*((XTUint8*)cur_p++) = disp;
	    }


						/* 1111 1111 : mod 100 r/m */
						static inline void jmpAbsoluteIndirectMemory(XTMemAddr addr)
						{
								*((XTUint8*)cur_p++) = 0xff;
								*((XTUint8*)cur_p++) = /* 00 100 101 */ 0x25;
								*((XTUint32*)cur_p) = addr;
								cur_p += 4;
						}

						/* 1111 1111 : 1110 0 reg*/
						static inline void jmpAbsoluteIndirectReg(XTRegNum reg)
						{
								*((XTUint8*)cur_p++) = 0xff;
								*((XTUint8*)cur_p++) = 0xe0 | reg;
						}

						/* 1110 1001 : full displacement */
						static inline void jmpRelativeDirectDisp32(XTInt32 disp)
						{
								*((XTUint8*)cur_p++) = 0xe9;
								putWord(disp);
						}

						/* 0000 1111 : 1000 tttn : full displacement */
						static inline void jccRelativeDirectDisp32(XTInt32 disp, XTUint8 tttn)
						{
								*((XTUint8*)cur_p++) = 0x0f;
								*((XTUint8*)cur_p++) = 0x80 | tttn;
								putWord(disp);
						}

						/* 0000 1111 : 1000 0100 : full displacement */
						static inline void jeRelativeDirectDisp32(XTInt32 disp)
						{
								*((XTUint8*)cur_p++) = 0x0f;
								*((XTUint8*)cur_p++) = 0x84;
								putWord(disp);
						}

						static inline void jneRelativeDirectDisp32(XTInt32 disp)
						{
								*((XTUint8*)cur_p++) = 0x0f;
								*((XTUint8*)cur_p++) = 0x85;
								putWord(disp);
						}

						// 1110 1000 : displacement32
						static inline void callRelativeDirectDisp32(XTInt32 disp)
						{
								*((XTUint8*)cur_p++) = 0xe8;
								putWord(disp);
						}

						// 0110 1000 : imm32
						static inline void pushImm32(XTInt32 imm32)
						{
								*((XTUint8*)cur_p++) = 0x68;
								putWord(imm32);
						}

						// 0x60
						static inline void pushAll()
						{
								*((XTUint8*)cur_p++) = 0x60;
						}

						// 0101 0 reg
						static inline void pushReg(XTRegNum reg)
						{
								*((XTUint8*)cur_p++) = 0x50 | reg;
						}

						// 0101 1 reg
						static inline void popReg(XTRegNum reg)
						{
								*((XTUint8*)cur_p++) = 0x58 | reg;
						}

						// 0x61
						static inline void popAll() 
						{
								*((XTUint8*)cur_p++) = 0x61;
						}

						// float-poXTInt32instruction

						//0xd9	,flds 32bit
						static inline void fpPushFreg32(XTMemAddr addr)
						{
								*((XTUint8*)cur_p++) = 0xd9;
								*((XTUint8*)cur_p++) = 0x05;
								*(XTMemAddr *)cur_p = addr;
								cur_p+=4;
						}

						static inline void fpPushFreg32BaseDisp(XTRegNum reg, XTInt32 disp)
						{
								*((XTUint8*)cur_p++) = 0xd9;
								*((XTUint8*)cur_p++) = 0x80 | reg;
								putWord(disp);
						}

						//0xdd	,fldl 64bit
						static inline void fpPushFreg64(XTMemAddr addr)
						{
								*((XTUint8*)cur_p++) = 0xdd;
								*((XTUint8*)cur_p++) = 0x05;
								*(XTMemAddr *)cur_p = addr;
								cur_p+=4;
						}

						static inline void fpPushFreg64BaseDisp(XTRegNum reg, XTInt32 disp)
						{
								*((XTUint8*)cur_p++) = 0xdd;
								*((XTUint8*)cur_p++) = 0x80 | reg;
								putWord(disp);
						}

	    //0xdf	,fild addr
	    static inline void intPushFreg16(MemAddr addr)
	    {
										*((XTUint8*)cur_p++) = 0xdf;
										*((XTUint8*)cur_p++) = 0x05;
										*(XTMemAddr *)cur_p = addr;
										cur_p+=4;
	    }

	    static inline void intPushFreg16BaseDisp(RegNum reg, Word disp)
	    {
		*((XTUint8*)cur_p++) = 0xdf;
		*((XTUint8*)cur_p++) = 0x80 | reg; 
		putWord(disp);
	    }


						//0xdb	,fildl addr
						static inline void intPushFreg32(XTMemAddr addr)
						{
								*((XTUint8*)cur_p++) = 0xdb;
								*((XTUint8*)cur_p++) = 0x05;
								*(XTMemAddr *)cur_p = addr;
								cur_p+=4;
						}

	    static inline void intPushFreg32BaseDisp(RegNum reg, Word disp)
	    {
										*((XTUint8*)cur_p++) = 0xdb;
										*((XTUint8*)cur_p++) = 0x80 | reg; 
										putWord(disp);
	    }


						//0xde	,fildll addr
						static inline void longlongPushFreg64(XTMemAddr addr)
						{
								*((XTUint8*)cur_p++) = 0xde;
								*((XTUint8*)cur_p++) = 0x2d;
								*(XTMemAddr *)cur_p = addr;
								cur_p+=4;
						}

	    //0xdf	,fildll addr
	    static inline void longlongPushFreg64BaseDisp(RegNum reg, Word disp)
	    {
		*((XTUint8*)cur_p++) = 0xdf;
		*((XTUint8*)cur_p++) = 0xa8 | reg; 
		putWord(disp);
	    }


						//0xd9	,fstps 32bit
						static inline void fpPopFreg32(XTMemAddr addr)
						{
								*((XTUint8*)cur_p++) = 0xd9;
								*((XTUint8*)cur_p++) = 0x1d;
								*(XTMemAddr *)cur_p = addr;
								cur_p+=4;
						}

						static inline void fpPopFreg32BaseDisp(XTRegNum reg, XTInt32 disp)
						{
								*((XTUint8*)cur_p++) = 0xd9;
								*((XTUint8*)cur_p++) = 0x98 | reg;
								putWord(disp);
						}

						//0xdd	,fstpl 64bit
						static inline void fpPopFreg64(XTMemAddr addr)
						{
								*((XTUint8*)cur_p++) = 0xdd;
								*((XTUint8*)cur_p++) = 0x1d;
								*(XTMemAddr *)cur_p = addr;
								cur_p+=4;
						}

						static inline void fpPopFreg64BaseDisp(XTRegNum reg, XTInt32 disp)
						{
								*((XTUint8*)cur_p++) = 0xdd;
								*((XTUint8*)cur_p++) = 0x98 | reg;
								putWord(disp);
						}

						//0xdb	,fistpl 32bit   
						static inline void intPopFreg32(XTMemAddr addr)
						{
								*((XTUint8*)cur_p++) = 0xdb;
								*((XTUint8*)cur_p++) = 0x1d;
								*(XTMemAddr *)cur_p = addr;
								cur_p+=4;
						}

	    static inline void intPopFreg32BaseDisp(RegNum reg, Word disp)
	    {
		*((XTUint8*)cur_p++) = 0xdb;
		*((XTUint8*)cur_p++) = 0x98 | reg; 
		putWord(disp);
	    }


						//0xdb	,fistpll 64bit
						static inline void longlongPopFreg64(XTMemAddr addr)
						{
								*((XTUint8*)cur_p++) = 0xde;
								*((XTUint8*)cur_p++) = 0x3d;
								*(XTMemAddr *)cur_p = addr;
								cur_p+=4;
						}

	    static inline void longlongPopFreg64BaseDisp (RegNum reg, Word disp)
	    {
		*((XTUint8*)cur_p++) = 0xdf;
		*((XTUint8*)cur_p++) = 0xb8 | reg;
		putWord(disp);
	    }


						//0xde	,FADDP1 32bit
						static inline void fpAdd32()
						{
								*((XTUint8*)cur_p++) = 0xde;
								*((XTUint8*)cur_p++) = 0xc1;
						}

						//0xde	,FADDP1 64bit
						static inline void fpAdd64()
						{
								*((XTUint8*)cur_p++) = 0xde;
								*((XTUint8*)cur_p++) = 0xc1;
						}

						//0xd8	,FSUBP1 32bit
						//ST(1)<-ST(1)-ST(0)
						//pop ST(0)
						static inline void fpSub32()
						{
								*((XTUint8*)cur_p++) = 0xde;
								*((XTUint8*)cur_p++) = 0xe9;
						}

						//0xd8	,FSUBP1 64bit
						//ST(1)<-ST(1)-ST(0)
						//pop ST(0)
						static inline void fpSub64()
						{
								*((XTUint8*)cur_p++) = 0xde;
								*((XTUint8*)cur_p++) = 0xe9;
						}
						// 0xde	,FMULTP 32/64
						static inline void fpMult32()
						{
								*((XTUint8*)cur_p++) = 0xde;
								*((XTUint8*)cur_p++) = 0xc9;
						}

						// 0xde	,FMULTP 32/64
						static inline void fpMult64()
						{
								*((XTUint8*)cur_p++) = 0xde;
								*((XTUint8*)cur_p++) = 0xc9;
						}

						// 0x	,FDIVP  32/64
						static inline void fpDiv32()
						{
								*((XTUint8*)cur_p++) = 0xde;
								*((XTUint8*)cur_p++) = 0xf9;
						}

						static inline void fpDiv64()
						{
								*((XTUint8*)cur_p++) = 0xde;
								*((XTUint8*)cur_p++) = 0xf9;
						}

						static inline void fpChs()
						{
								*((XTUint8*)cur_p++) = 0xd9;
								*((XTUint8*)cur_p++) = 0xe0;
						}

						static inline void fpSqrt()
						{
								*((XTUint8*)cur_p++) = 0xd9;
								*((XTUint8*)cur_p++) = 0xfa;
						}

						static inline void fabs()
						{
								*((XTUint8*)cur_p++) = 0xd9;
								*((XTUint8*)cur_p++) = 0xe1;
						}

						static inline void fldcw( XTMemAddr addr )
						{*((XTUint8*)cur_p++) = 0xdb; *((XTUint8*)cur_p++)=0xe2;
								*((XTUint8*)cur_p++) = 0xd9;
								*((XTUint8*)cur_p++) = 0x2d;
								putWord(addr);
						}

						static inline void fstcw( XTMemAddr addr )
						{*((XTUint8*)cur_p++) = 0x9b;
								*((XTUint8*)cur_p++) = 0xd9;
								*((XTUint8*)cur_p++) = 0x3d;
								putWord(addr);
						}

	    static inline void fnstsw()
	    {
		*((XTUint8*)cur_p++) = 0xdf;
		*((XTUint8*)cur_p++) = 0xe0;
	    }


						static inline void fincstp()
						{
								*((XTUint8*)cur_p++) = 0xdd;
								*((XTUint8*)cur_p++) = 0xc0;
								*((XTUint8*)cur_p++) = 0xd9;
								*((XTUint8*)cur_p++) = 0xf7;
						}

	    static inline void fpFrndint()
	    {
		*((XTUint8*)cur_p++) = 0xd9;
		*((XTUint8*)cur_p++) = 0xfc;
	    }

	    static inline void fpFchs()
	    {
		*((XTUint8*)cur_p++) = 0xd9;
		*((XTUint8*)cur_p++) = 0xe0;
	    }

	    static inline void fpFxam()
	    {
		*((XTUint8*)cur_p++) = 0xd9;
		*((XTUint8*)cur_p++) = 0xe5;
	    }

	    static inline void fpFldlg2()
	    {
		*((XTUint8*)cur_p++) = 0xd9;
		*((XTUint8*)cur_p++) = 0xec;
	    }

	    static inline void fpFldln2()
	    {
		*((XTUint8*)cur_p++) = 0xd9;
		*((XTUint8*)cur_p++) = 0xed;
	    }

	    static inline void fpFldl2e()
	    {
		*((XTUint8*)cur_p++) = 0xd9;
		*((XTUint8*)cur_p++) = 0xea;
	    }

	    static inline void fpFyl2x()
	    {
		*((XTUint8*)cur_p++) = 0xd9;
		*((XTUint8*)cur_p++) = 0xf1;
	    }

	    static inline void fpFyl2xp1()
	    {
		*((XTUint8*)cur_p++) = 0xd9;
		*((XTUint8*)cur_p++) = 0xf9;
	    }

	    static inline void fpF2xm1()
	    {
		*((XTUint8*)cur_p++) = 0xd9;
		*((XTUint8*)cur_p++) = 0xf0;
	    }

	    static inline void fpFscale()
	    {
		*((XTUint8*)cur_p++) = 0xd9;
		*((XTUint8*)cur_p++) = 0xfd;
	    }

	    static inline void fpFcos()
	    {
		*((XTUint8*)cur_p++) = 0xd9;
		*((XTUint8*)cur_p++) = 0xff;
	    }

	    static inline void fpFsin()
	    {
		*((XTUint8*)cur_p++) = 0xd9;
		*((XTUint8*)cur_p++) = 0xfe;
	    }

	    static inline void fpFptan()
	    {
		*((XTUint8*)cur_p++) = 0xd9;
		*((XTUint8*)cur_p++) = 0xf2;
	    }


						//0xcc
						//Added by Zheng Juyu, for single break
						static inline void sbreak()
						{
								*((XTUint8*)cur_p++) = 0xcc;
						}

	    // 0x0f bc
	    // bsf
	    static inline void bsf(RegNum src, RegNum dst)
	    {
	        *((XTUint8*)cur_p++) = 0x0f;
		       *((XTUint8*)cur_p++) = 0xbc;
		       *((XTUint8*)cur_p++) = 0xc0 | dst << 3 | src; 
	    }

	    // 0x0f bd
	    // bsr
	    static inline void bsr(RegNum src, RegNum dst)
	    {
	        *((XTUint8*)cur_p++) = 0x0f;
		       *((XTUint8*)cur_p++) = 0xbd;
		       *((XTUint8*)cur_p++) = 0xc0 | dst << 3 | src; 
	    }

				private:
						static XTMemAddr cur_p;

						//												static struct RegisterFile saved;

		};

}
#endif
